/**
 * @PROJECT 
 * @DATE 2018年7月10日 下午7:17:03
 * @AUTHOR LUYU
 */
package com.kool.tlwp.generator;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;

import com.kool.tlwp.bean.IoFieldVo;
import com.kool.tlwp.exception.AppException;
import com.kool.tlwp.generator.context.VueContext;
import com.kool.tlwp.util.DateUtils;
import com.kool.tlwp.util.PropertyUtils;

import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * @DESCRIBE
 * @AUTHOR LUYU
 * @DATE 2018年7月10日 下午7:17:03
 *
 */
public class VueCodeGenerator extends CodeGenerator {

	/**
	 * @param context
	 * @throws AppException
	 */
	public VueCodeGenerator(VueContext context) throws AppException {
		super(context);
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月10日 下午7:17:20
	 *
	 * @throws AppException
	 */
	@Override
	public void generate() throws AppException {
		VueContext vc = (VueContext) context;
		String destDir = vc.getDestDir() + "\\"
				+ DateUtils.getCurrentTimeString(DateUtils.FORMAT_DATE_AND_TIME_WITHOUT_SPLIT);
		String upName = vc.getBusinessName();
		String lowName = upName.substring(0, 1).toLowerCase() + upName.substring(1);
		String vueDir = getVueDir(destDir, lowName);
		try {
			Template template = configuration.getTemplate("vue.ftl");
			template.setOutputEncoding("UTF-8");
			HashMap<String, Object> map = getVueMap(vc);
			Writer writer = getVueWriter(upName, vueDir);
			template.process(map, writer);
			writer.flush();
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
			throw new AppException("操作Template文件错误!", e);
		} catch (TemplateException e) {
			e.printStackTrace();
			throw new AppException("操作Template文件错误!", e);
		} catch (Exception e) {
			e.printStackTrace();
			throw new AppException("工具发生错误!", e);
		}
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月10日 下午7:32:53
	 *
	 * @param name
	 * @param vueDir
	 * @return
	 */
	private Writer getVueWriter(String name, String vueDir) throws Exception {
		String fileName = name + "Mng.vue";
		String destPath = vueDir + "\\" + fileName;
		Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destPath), "UTF-8"));
		return writer;
	}

	/**
	 * @DESCRIBE
	 * @DATE 2018年7月10日 下午7:32:48
	 *
	 * @param vc
	 * @return
	 * @throws Exception
	 */
	private HashMap<String, Object> getVueMap(VueContext vc) throws Exception {
		HashMap<String, Object> map = new HashMap<String, Object>();
		String upName = vc.getBusinessName();
		String lowName = upName.substring(0, 1).toLowerCase() + upName.substring(1);
		map.put("lowBusinessName", lowName);

		String queryIn = vc.getQueryIn();
		List<IoFieldVo> list = json2IoVoList(queryIn);
		int col = 3;
		List<List<IoFieldVo>> listRows = new ArrayList<>();
		List<IoFieldVo> listCols = new ArrayList<>();
		for (IoFieldVo vo : list) {
			if (col > 0) {
				listCols.add(vo);
				col--;
			} else {
				listRows.add(listCols);
				col = 2;
				listCols = new ArrayList<>();
				listCols.add(vo);
			}
		}
		if (listCols.size() > 0) {
			listRows.add(listCols);
		}
		map.put("conditionRows", listRows);

		String queryOut = vc.getQueryOut();
		List<IoFieldVo> listQueryOut = json2IoVoList(queryOut);
		map.put("tableFields", listQueryOut);

		map.put("chnBusinessName", vc.getChnBusinessName());

		List<IoFieldVo> listAddIn = json2IoVoList(vc.getAddIn());
		List<IoFieldVo> listAddL = new ArrayList<>();
		List<IoFieldVo> listAddR = new ArrayList<>();
		int sizeAddIn = listAddIn.size();
		for (int i = 0; i < sizeAddIn; i++) {
			if (i % 2 == 0) {
				listAddL.add(listAddIn.get(i));
			} else if (i % 2 == 1) {
				listAddR.add(listAddIn.get(i));
			}
		}
		map.put("addFormFieldsL", listAddL);
		map.put("addFormFieldsR", listAddR);

		List<IoFieldVo> listUpdateIn = json2IoVoList(vc.getUpdateIn());
		List<IoFieldVo> listUpdateL = new ArrayList<>();
		List<IoFieldVo> listUpdateR = new ArrayList<>();
		int sizeUpdateIn = listUpdateIn.size();
		for (int i = 0; i < sizeUpdateIn; i++) {
			if (i % 2 == 0) {
				listUpdateL.add(listUpdateIn.get(i));
			} else if (i % 2 == 1) {
				listUpdateR.add(listUpdateIn.get(i));
			}
		}
		map.put("updateFormFieldsL", listUpdateL);
		map.put("updateFormFieldsR", listUpdateR);

		map.put("queryIn", vc.getQueryIn());
		map.put("queryUrl", vc.getQueryUrl());
		map.put("queryPageUrl", vc.getQueryPageUrl());
		map.put("queryOut", vc.getQueryOut());
		map.put("addIn", vc.getAddIn());
		map.put("addUrl", vc.getAddUrl());
		map.put("updateIn", vc.getUpdateIn());
		map.put("updateUrl", vc.getUpdateUrl());
		map.put("deleteIn", vc.getDeleteIn());
		map.put("deleteUrl", vc.getDeleteUrl());

		map.put("addInFields", listAddIn);
		map.put("updateInFields", listUpdateIn);

		boolean hasDateTimeOrDate = false;
		for (IoFieldVo field : listQueryOut) {
			if (field.getType() != null && (field.getType().equals("datetime") || field.getType().equals("date"))) {
				hasDateTimeOrDate = true;
				break;
			}
		}
		map.put("hasDateTimeOrDate", hasDateTimeOrDate);
		return map;
	}

	public static void main(String[] args) throws AppException {
		VueContext context = new VueContext();
		Properties prop = null;
		try {
			prop = PropertyUtils.getSysPropFromRoot();
		} catch (IOException e) {
			throw new AppException("加载properties文件时，发生异常！", e);
		}
		context.setTemplateDir(prop.getProperty("TEMPLATE"));
		context.setIoDir(prop.getProperty("IO_DIR"));
		context.setDestDir(prop.getProperty("DIR"));

		context.setUrl(prop.getProperty("URL"));
		context.setDriver(prop.getProperty("DRIVER"));
		context.setName(prop.getProperty("USER"));
		context.setPwd(prop.getProperty("PWD"));

		context.setBusinessName(prop.getProperty("BUSINESS_NAME"));
		context.setChnBusinessName(prop.getProperty("CHN_BUSINESS_NAME"));
		context.setAddIn(prop.getProperty("ADD_IN"));
		context.setAddUrl(prop.getProperty("ADD_URL"));
		context.setUpdateIn(prop.getProperty("UPDATE_IN"));
		context.setUpdateUrl(prop.getProperty("UPDATE_URL"));
		context.setDeleteIn(prop.getProperty("DELETE_IN"));
		context.setDeleteUrl(prop.getProperty("DELETE_URL"));
		context.setQueryIn(prop.getProperty("QUERY_IN"));
		context.setQueryOut(prop.getProperty("QUERY_OUT"));
		context.setQueryUrl(prop.getProperty("QUERY_URL"));
		context.setQueryPageUrl(prop.getProperty("QUERY_PAGE_URL"));
		CodeGenerator genr = new VueCodeGenerator(context);
		genr.generate();
	}
}
